﻿
// ## 2022/12/11 # 铃 # 统合所有的调度功能的算法

namespace AI全局调度
{

	/// =========================================================================================

	const bool 调试模式 = false;
	const bool 调试模式2 = false;

	class Main
	{
		pk::list<pk::person @> actors;
		array<int> base_want_person_for707(据点_末, 0);
		array<int> base_diff_person_for707(据点_末, 0);

		Main()
		{

			pk::bind(202, pk::trigger202_t(onAIRunningOrder));
		}


		//------------------------------------------------------------------------------------------------------------------------------
		//                                        据点调度
		//------------------------------------------------------------------------------------------------------------------------------

		//******************************************调度前判决**************************************
		void onAIRunningOrder(pk::ai_context @context, pk::building @building, int cmd)
		{
			if (cmd == 据点AI_据点调度)
			{
				int building_force_id = building.get_force_id();
				pk::force @force = pk::get_force(building.get_force_id());
				pk::ai_context_base @base = context.base[building.get_id()];
				pk::district @district = pk::get_district(building.get_district_id());
				int force_person_count = pk::get_person_list(force, pk::mibun_flags(身份_君主, 身份_都督, 身份_太守, 身份_一般)).count;
				int district_person_count = pk::get_person_list(district, pk::mibun_flags(身份_君主, 身份_都督, 身份_太守, 身份_一般)).count;

			//第一次循环,对所有据点进行赋值(不然寻找据点的时候会存在还未赋值的据点)
				for (int i = 0; i < 据点_末; i++)
				{
					array<pk::building @> src_base_arr;
					pk::district @district0 = pk::get_district(pk::get_building(i).get_district_id());

					//玩家军团和电脑不同处理办法
					if (!force.is_player())
					{
						base_want_person_for707[i] = ai::base_want_person[i];
						base_diff_person_for707[i] = ai::base_want_person[i] - ai::base_real_person[i];

					}
					else if (force.is_player() and district0 !is null and district0.get_id() >= 0 and district0.get_id() < 军团_末)
					{
						base_want_person_for707[i] = ai::base_want_person_for_district[i];

					}
				}

				if (调试模式2)
				{
					pk::trace(pk::format("1{}前置判断,707需要武将{},据点需要武将_势力{},据点需要武将_军团{}", pk::decode(pk::get_name(building)), base_want_person_for707[building.get_id()], ai::base_want_person[building.get_id()], ai::base_want_person_for_district[building.get_id()]));
					pk::trace(pk::format("1{}前置判断,据点分{},军团总分{},势力总分{},军团武将{},势力武将{}", pk::decode(pk::get_name(building)), ai::base_score[building.get_id()], ai::district_score[district.get_id()], ai::force_score[force.get_id()], district_person_count, force_person_count));

				}

				//玩家控制的城市完全不能移动
				if (pk::is_player_controlled(building))
					return;

				if (ai::base_real_person[building.get_id()] < 3)
					return;

				if (调试模式2) pk::trace(pk::format("2{}前置判断", pk::decode(pk::get_name(building))));

				if (main.base_want_person_for707[building.get_id()] > ai::base_real_person[building.get_id()] + 2)
					return;

				if (调试模式2) pk::trace(pk::format("3{}前置判断", pk::decode(pk::get_name(building))));

				if (ai::base_real_person[building.get_id()] < 3)
					return;

				if (调试模式2) pk::trace(pk::format("4{}前置判断", pk::decode(pk::get_name(building))));

				if (ai::base_in_range_enemy_troops[building.get_id()] > 0)
					return;

				if (调试模式2) pk::trace(pk::format("5{}前置判断", pk::decode(pk::get_name(building))));

				array<pk::building @> dst_base_arr = 寻找据点列表(building);

				if (dst_base_arr.length == 0)
					return;

				// 候选据点的优先顺序  所需差距越大 越优先
				dst_base_arr.sort(function(a, b) { return  main.base_diff_person_for707[a.get_id()] + (ai::base_real_person[a.get_id()] == 0 ? 5 : 0) > main.base_diff_person_for707[b.get_id()] + (ai::base_real_person[b.get_id()] == 0 ? 5 : 0); });

				pk::building @dst_base = dst_base_arr[0];
				int dst_id = dst_base.get_id();

				auto idle_person_list = pk::get_idle_person_list(pk::get_building(building.get_id()));
				auto person_list = pk::get_person_list(pk::get_building(building.get_id()), pk::mibun_flags(身份_都督, 身份_太守, 身份_一般));

				//移动人数为目标需要和我能提供的最小值
				int 移动人数 = pk::min(main.base_want_person_for707[dst_id] - ai::base_real_person[dst_id], ai::base_real_person[building.get_id()] - main.base_want_person_for707[building.get_id()]);

				if (调试模式2) pk::trace(pk::format("8{}前置判断,目标:{},移动人数{},我的真实人数{},我的合意人数{}", pk::decode(pk::get_name(building)), pk::decode(pk::get_name(dst_base)), 移动人数, ai::base_real_person[building.get_id()], main.base_want_person_for707[building.get_id()]));


				//小城市需要的人数不超过8人.
				if (dst_id >= 据点_末)
					移动人数 = pk::min(8 - ai::base_real_person[dst_id], 移动人数);

				//关隘需要的人数不超过5人.
				if (dst_base_arr[0].facility == 设施_关隘)
					移动人数 = pk::min(5 - ai::base_real_person[dst_id], 移动人数);

				if (移动人数 <= 0) return;

				if (调试模式2) pk::trace(pk::format("9{}前置判断,移动人数{}", pk::decode(pk::get_name(building)), 移动人数));

				person_list.sort(function(a, b) {
					return (a.stat[武将能力_统率] * 2 + a.stat[武将能力_武力] + a.stat[武将能力_智力] + pk::rand(30) - a.kouseki / 500) > b.stat[武将能力_统率] * 2 + b.stat[武将能力_武力] + b.stat[武将能力_智力] + pk::rand(30) - b.kouseki / 500;
				});

				pk::list<pk::person @> actors;
				int j = 0;
				for (int i = 0; i < person_list.count; i++)
				{

					if (pk::is_absent(person_list[i]) or pk::is_unitize(person_list[i]))
						continue;
					if (person_list[i].action_done == true)
						continue;

					// 如果出发城市城市正在战斗中,不给出最好的1/3
					if (ai::base_statue[building.get_id()] == 据点_兵临)
					{
						if (i < person_list.count / 2)
							continue;
					}

					// 如果出发城市城市是危险前线,不给出最好的1/2
					if (ai::base_statue[building.get_id()] == 据点_危险)
					{
						if (i < person_list.count / 2)
							continue;
					}

					// 如果出发城市城市是普通前线,不给出最好的2/3
					if (ai::base_statue[building.get_id()] == 据点_前线)
					{
						if (i < person_list.count / 3 * 2)
							continue;
					}

					// 小城市也不拿走最好的前1/10
					if (dst_id >= 城市_末)
					{
						if (i < person_list.count / 10)
							continue;
					}

					// 即使是兵临状态下,小城市也不拿走最好的前1/8
					if (ai::base_statue[dst_id] == 据点_兵临 and building.get_id() >= 城市_末)
					{
						if (i < person_list.count / 8)
							continue;
					}

					// 即使是战斗状态下,小城市也不拿走最好的前1/6
					if (ai::base_statue[dst_id] == 据点_战斗 and building.get_id() >= 城市_末)
					{
						if (i < person_list.count / 6)
							continue;
					}

					// 即使是危险状态下,小城市也不拿走最好的前1/5
					if (ai::base_statue[dst_id] == 据点_危险 and building.get_id() >= 城市_末)
					{
						if (i < person_list.count / 5)
							continue;
					}

					// 普通前线不拿走最好的1/3
					if (ai::base_statue[dst_id] == 据点_前线)
					{
						if (i < person_list.count / 3)
							continue;
					}

					// 非前线不拿走最好的1/2
					if (ai::base_statue[dst_id] == 据点_警戒 or ai::base_statue[dst_id] == 据点_后方)
					{
						if (i < person_list.count / 2)
							continue;
					}



					// 一些特别重要的大城市才有用的特技,就不要调度给小城了
					if (building.get_id() >= 城市_末 and (ch::has_skill(person_list[i], 特技_富豪) or ch::has_skill(person_list[i], 特技_征税) or ch::has_skill(person_list[i], 特技_米道) or ch::has_skill(person_list[i], 特技_征收)))
						continue;
					j++;
					actors.add(person_list[i]);
					person_list[i].action_done = true;
					string person_name2 = pk::format("\x1b[1x{}\x1b[0x", pk::decode(pk::get_name(person_list[i])));

					if (调试模式)
					{
						string person_name = pk::format("\x1b[1x{}\x1b[0x", pk::decode(pk::get_name(person_list[i])));
						string building_name = pk::format("\x1b[1x{}\x1b[0x", pk::decode(pk::get_name(building)));
						string dst_name = pk::format("\x1b[1x{}\x1b[0x", pk::decode(pk::get_name(dst_base_arr[0])));
						string action_message = pk::format("{}向{}移动了{}", building_name, dst_name, person_name);
						pk::trace(pk::format("{}向{}移动了{}", building_name, dst_name, person_name));
					}
					if (j >= 移动人数)
						break;
				}

				// 移动命令
				pk::move_cmd_info cmd_move;
				@cmd_move.base = building;
				@cmd_move.target = dst_base_arr[0];
				cmd_move.actors = actors;
				pk::command(cmd_move);

				ch::remove_idle_person(context, actors);
			}
		}

			//*********************可调度的候选据点****************

		array<pk::building @> 寻找据点列表(pk::building @building)
		{
			array<pk::building @> dst_base_arr;
			for (int i = 0; i < 据点_末; i++)
			{
				pk::building @dst_base = pk::get_building(i);

				if (!pk::is_alive(dst_base))
					continue;

				if (dst_base.get_force_id() != building.get_force_id())
					continue;

				if (i == building.get_id())
					continue;

				if (调试模式2) pk::trace(pk::format("5{}寻找判断{}", pk::decode(pk::get_name(building)), pk::decode(pk::get_name(dst_base))));

				int city_distance = pk::get_city_distance(pk::get_city_id(building.pos), pk::get_city_id(dst_base.pos));

				//需要大于3回合的也不要
				if (city_distance > 3)
					continue;

				pk::district @dst_district = pk::get_district(dst_base.get_district_id());
				pk::district @src_district = pk::get_district(building.get_district_id());

				if (building.is_player())
				{
					if (src_district.no != dst_district.no)
						continue;
				}

				//小城市超过8个人就不用再调度了
				if (i >= 据点_末 and ai::base_real_person[i] >= 8)
					continue;

				if (调试模式2) pk::trace(pk::format("6{}寻找判断{}", pk::decode(pk::get_name(building)), pk::decode(pk::get_name(dst_base))));

				//人数超标也不会被选中
				if (ai::base_real_person[i] > main.base_want_person_for707[i] + 3)
					continue;

				if (调试模式2)
				{

					pk::trace(pk::format("7{}寻找判断{}", pk::decode(pk::get_name(building)), pk::decode(pk::get_name(dst_base))));

					pk::trace(pk::format("7{}寻找判断{},目标所需{},目标真实{}", pk::decode(pk::get_name(building)), pk::decode(pk::get_name(dst_base)), main.base_want_person_for707[i], ai::base_real_person[i]));
				}
				dst_base_arr.insertLast(dst_base);
			}

			return dst_base_arr;
		}

	} Main main;

}